<?php

namespace Pinenut\Form;

use Pinenut\Request;

/**
 * Базовый класс элемента формы
 * TODO: отрефакторить - config расписать в сам элемент
 * TODO: внедрить возможность нескольких мастер-значений
 */
class Element
{
	protected $config;

	protected $isSlave;

	protected $masterValue;

	protected $partial;

	protected $defaultPathToElements = 'forms.render';
	protected $defaultPathToFilters = 'forms.filter';
	protected $defaultPathToValidators= 'forms.validator';

	public $type;
	
	public function __construct($config)
	{
		$this->config = $config;
		$this->isSlave = empty($this->config['master']) ? false : true;
		$this->type = $this->config['type'];
		
	
	}

	/**
	 * Хелпер для вызова действия в контексте текущего
	 * TODO: оформить в подключаемый хелпер (в виде trait)
	 *
	 * @param string $action имя действия
	 * @param array $params	параметры вызова
	 * @param string|null $view имя шаблона для этого действия
	 * @return \Pinenut\Response
	 */
	function action($action, array $params = array(), $view = null, $deferred = true)
	{
		$dispatcher = \Application::$DispatcherServiceClass;

		// $this->defaultPathToElements . '.' .
		$response = $dispatcher::action(new Request( $action, $params, $view, $deferred));

		return $response;
	}

	public function render($view = null)
	{
		return $this->action($this->defaultPathToElements . '.' .$this->config['type'], $this->config, $view);
	}

	public function getValue()
	{
		return array_key_exists('value', $this->config) ? $this->config['value'] : null;
	}

	public function isSubmit()
	{
		return 'submit' == strtolower($this->config['type']);
	}

	public function setValue($value)
	{
		$this->config['value'] = $value;
		return $this;
	}

	public function setParital($isIt)
	{
		$this->partial = !!$isIt;
	}

	public function isPartial()
	{
		return $this->partial;
	}

	public function isSlave()
	{
		return $this->isSlave;
	}

	public function isMaster()
	{
		return !$this->isSlave(); /* todo пофиксить */
	}

	public function getStyle()
	{
		return isset($this->config['style']) ? $this->config['style'] : null;
	}

	public function dividerAfter()
	{
		return isset($this->config['dividerAfter']) ? $this->config['dividerAfter'] : false;
	}

	public function dividerBefore()
	{
		return isset($this->config['dividerBefore']) ? $this->config['dividerBefore'] : false;
	}

	public function getMasterName()
	{
		if (!$this->isSlave()) {
			return;
		}

		return $this->config['master'];
	}

	public function setMasterValue($value)
	{
		$this->config['masterValue'] = $value;
	}
	
	public function getMasterValue()
	{
		return $this->config['masterValue'];
	}

	public function filter()
	{
		if (empty($this->config['filters'])) {
			return;
		}
		$this->setValue($this->action($this->defaultPathToFilters . '.' . $this->config['filters'], array('value' => $this->getValue()))->content);
	}

	public function validate()
	{
		$isValid = true;

		if (empty($this->config['validators'])) {
			return $isValid;
		}

		// разбираю список валидаторов и вызываю их по очереди
		foreach ((array)$this->config['validators'] as $key => $value) {
			$validatorParams = array('value' => $this->getValue());
			
			// добавляем в параметры значение мастера, если указано
			if ($this->getMasterName()) {
				$validatorParams['masterValue'] = $this->getMasterValue();
			}

			if (is_string($key)) {
				$validatorName = $key;
				$validatorParams = array_merge($validatorParams, $value);
			} else {
				$validatorName = $value;
			}

			if ($errorMessage = $this->action($this->defaultPathToValidators . '.' . $validatorName, $validatorParams)->content) {
				$isValid = false;
				$this->config['errors'][] = $errorMessage;
			}
		}

		return $isValid;
	}
	public function addErrors($errors) {
		$this->config['errors'] = array_merge((array)@$this->config['errors'], (array)$errors);
	}
}